﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace OneDark
{
    //
    // 摘要:
    //     指定 SQL Server 特定数据类型的字段、 属性，用于 System.Data.SqlClient.SqlParameter。
    public enum SqlDbType
    {
        //
        // 摘要:
        //     System.Int64。 64 位带符号整数。
        BigInt = 0,

        //
        // 摘要:
        //     System.Array类型System.Byte。 固定长度流，范围在 1 到 8000 个字节之间的二进制数据。
        Binary = 1,

        //
        // 摘要:
        //     System.Boolean。 无符号的数字值，可为 0，1，或 null。
        Bit = 2,

        //
        // 摘要:
        //     System.String。 范围在 1 到 8000 个字符之间的非 Unicode 字符固定长度流。
        Char = 3,

        //
        // 摘要:
        //     System.DateTime。 日期和时间数据，值范围从 1753 年 1 月 1 日至 12 月 31 日，精确到 3.33 毫秒到 9999。
        DateTime = 4,

        //
        // 摘要:
        //     System.Decimal。 固定的精度和小数位数之间的数值范围为-10 38 -1 和 10 38 -1。
        Decimal = 5,

        //
        // 摘要:
        //     System.Double。 浮点数，范围在-1.79 e + 308 到 1.79 e + 308 之间。
        Float = 6,

        //
        // 摘要:
        //     System.Array类型System.Byte。 范围从 0 到 2 的二进制数据的长度可变的流 31 -1 （或者 2147483647） 字节。
        Image = 7,

        //
        // 摘要:
        //     System.Int32。 32 位带符号整数。
        Int = 8,

        //
        // 摘要:
        //     System.Decimal。 货币值，范围从-2 63 （即-9223372036854775808） 到 2 63 -1 （或 9223372036854775807），精确到货币单位的万分之一。
        Money = 9,

        //
        // 摘要:
        //     System.String。 范围在 1 到 4000 个字符之间的 Unicode 字符的固定长度流。
        NChar = 10,

        //
        // 摘要:
        //     System.String。 最大长度为 2 Unicode 数据的长度可变的流 30 -1 （或者 1073741823） 个字符。
        NText = 11,

        //
        // 摘要:
        //     System.String。 范围在 1 到 4000 个字符之间的 Unicode 字符长度可变的流。 如果字符串大于 4000 个字符，隐式转换将失败。
        //     使用字符串长度超过 4000 个字符时，请显式设置对象。 使用 System.Data.SqlDbType.NVarChar 数据库列时 nvarchar(max)。
        NVarChar = 12,

        //
        // 摘要:
        //     System.Single。 浮点数，范围在-3.40 e + 38 到 3.40 e + 38 之间。
        Real = 13,

        //
        // 摘要:
        //     System.Guid。 全局唯一标识符 （或 GUID） 中。
        UniqueIdentifier = 14,

        //
        // 摘要:
        //     System.DateTime。 数值范围从 1900 年 1 月 1 日到 2079 年 6 月 6 日精度为一分钟的日期和时间数据。
        SmallDateTime = 15,

        //
        // 摘要:
        //     System.Int16。 16 位带符号整数。
        SmallInt = 16,

        //
        // 摘要:
        //     System.Decimal。 一个范围从-214，748.3648 到 +214,748.3647，精确到货币单位的万分之一的货币值。
        SmallMoney = 17,

        //
        // 摘要:
        //     System.String。 最大长度为 2 的非 Unicode 数据的变量长度流 31 -1 （或者 2147483647） 个字符。
        Text = 18,

        //
        // 摘要:
        //     System.Array类型System.Byte。 自动生成二进制数字，保证在数据库中是唯一。 timestamp 通常用作为表行加版本戳的机制。 存储大小为
        //     8 个字节。
        Timestamp = 19,

        //
        // 摘要:
        //     System.Byte。 8 位无符号整数。
        TinyInt = 20,

        //
        // 摘要:
        //     System.Array类型System.Byte。 范围在 1 到 8000 个字节之间的二进制数据长度可变的流。 如果字节数组大于 8000 个字节，隐式转换将失败。
        //     在使用字节数组大于 8000 个字节时，请显式设置对象。
        VarBinary = 21,

        //
        // 摘要:
        //     System.String。 范围在 1 到 8000 个字符之间的非 Unicode 字符长度可变的流。 使用 System.Data.SqlDbType.VarChar
        //     数据库列时 varchar(max)。
        VarChar = 22,

        //
        // 摘要:
        //     System.Object。 可以包含数值的特殊数据类型，字符串、 二进制文件中，或日期数据，以及 SQL Server 值的空和 Null，这将假定如果没有其他声明类型。
        Variant = 23,

        //
        // 摘要:
        //     XML 值。 获取将 XML 作为字符串使用 System.Data.SqlClient.SqlDataReader.GetValue(System.Int32)
        //     方法或 System.Data.SqlTypes.SqlXml.Value 属性，或指定为 System.Xml.XmlReader 通过调用 System.Data.SqlTypes.SqlXml.CreateReader
        //     方法。
        Xml = 25,

        //
        // 摘要:
        //     一个 SQL Server 用户定义类型 (UDT)。
        Udt = 29,

        //
        // 摘要:
        //     用于指定包含在表值参数中的结构化的数据的特殊数据类型。
        Structured = 30,

        //
        // 摘要:
        //     日期数据，从 1 月的值范围为 1，1 AD 到公元 9999 年 12 月 31 日。
        Date = 31,

        //
        // 摘要:
        //     基于 24 小时制时间数据。 时间值范围是 00:00:00 到 23:59:59.9999999 100 纳秒精度。 对应于 SQL Server time
        //     值。
        Time = 32,

        //
        // 摘要:
        //     日期和时间数据。 日期值范围是从 1 月 1，1 AD 到公元 9999 年 12 月 31 日。 时间值范围是 00:00:00 到 23:59:59.9999999
        //     100 纳秒精度。
        DateTime2 = 33,

        //
        // 摘要:
        //     时区的日期和时间数据。 日期值范围是从 1 月 1，1 AD 到公元 9999 年 12 月 31 日。 时间值范围是 00:00:00 到 23:59:59.9999999
        //     100 纳秒精度。 时区值范围是-14:00 至 + 14:00。
        DateTimeOffset = 34
    }

    public class TblCol
    {
        public int ColIndex { get; set; }

        public string ColName { get; set; }

        public string ColDesc { get; set; }

        public SqlDbType DataType { get; set; }

        public int Length { get; set; }

        public int Precision { get; set; }

        public bool Primary { get; set; }

        public bool Nullable { get; set; }

        public string EnumType { get; set; }

        public static SqlDbType GetSqlDbType(string strDT)
        {
            foreach (SqlDbType item in Enum.GetValues(typeof(SqlDbType)))
            {
                if (strDT.ToLower() == item.ToString().ToLower())
                {
                    return item;
                }
            }
            return SqlDbType.Int;
        }

        /// <summary>
        /// 获取参数声明
        /// </summary>
        /// <returns></returns>
        public string GetParamDecl()
        {
            string strPara = "new SqlParameter(\"@";
            strPara += ColName;
            strPara += "\", SqlDbType.";
            strPara += DataType.ToString();
            if (Length != 0)
            {
                strPara += " ," + Length.ToString();
            }
            strPara += ")";
            return strPara;
        }

        public string GetParamContent()
        {
            string strPara = "parameters[";
            strPara += ColIndex.ToString() + "].Value = model.";
            strPara += ColName + ";";
            return strPara;
        }

        public string GetParamModel()
        {
            string strPara = "if (row[\"" + ColName + "\"] != null";

            if (DataType == SqlDbType.Int)
            {
                strPara += " && !string.IsNullOrEmpty(row[\"" + ColName + "\"].ToString()))";
                strPara += "\r\n{\r\n\t";
                strPara += "model." + ColName + " = ";
                strPara += "int.Parse(row[\"" + ColName + "\"].ToString());";
                strPara += "\r\n}\r\n";
            }
            else if (DataType == SqlDbType.Float)
            {
                strPara += " && !string.IsNullOrEmpty(row[\"" + ColName + "\"].ToString()))";
                strPara += "\r\n{\r\n\t";
                strPara += "model." + ColName + " = ";
                strPara += "float.Parse(row[\"" + ColName + "\"].ToString());";
                strPara += "\r\n}\r\n";
            }
            else if (DataType == SqlDbType.Decimal)
            {
                strPara += " && !string.IsNullOrEmpty(row[\"" + ColName + "\"].ToString()))";
                strPara += "\r\n{\r\n\t";
                strPara += "model." + ColName + " = ";
                strPara += "decimal.Parse(row[\"" + ColName + "\"].ToString());";
                strPara += "\r\n}\r\n";
            }
            else if (DataType == SqlDbType.DateTime)
            {
                strPara += " && !string.IsNullOrEmpty(row[\"" + ColName + "\"].ToString()))";
                strPara += "\r\n{\r\n\t";
                strPara += "model." + ColName + " = ";
                strPara += "DateTime.Parse(row[\"" + ColName + "\"].ToString());";
                strPara += "\r\n}\r\n";
            }
            else if (!string.IsNullOrEmpty(EnumType))
            {
                strPara += ")";
                strPara += "\r\n{\r\n\t";
                strPara += "model." + ColName + " = ";  //(SqlDbType)Enum.Parse(typeof(SqlDbType), dataType)
                strPara += "(" + EnumType + ")Enum.Parse(typeof(" + EnumType + "), ";
                strPara += "row[\"" + ColName + "\"].ToString());";
                strPara += "\r\n}\r\n";
            }
            else
            {
                strPara += ")";
                strPara += "\r\n{\r\n\t";
                strPara += "model." + ColName + " = ";
                strPara += "row[\"" + ColName + "\"].ToString();";
                strPara += "\r\n}\r\n";
            }
            return strPara;
        }

        public string GetAppendPara()
        {
            return "strSql.Append(\"" + ColName + " = @" + ColName + ",\");";
        }
    }

    public class TblCfg
    {
        public string TableName { get; set; }

        public string ClassName { get; set; }

        public string FileName { get; set; }

        public string NameSpace { get; set; }

        public List<TblCol> TblCols = new List<TblCol>();

        /// <summary>
        /// 获取以逗号分隔的列名
        /// </summary>
        /// <returns></returns>
        public string GetColNameLst(string strSpl = "")
        {
            string tmpStr = string.Empty;
            TblCols.OrderBy(n => n.ColIndex);
            foreach (var col in TblCols)
            {
                tmpStr += strSpl;
                tmpStr += col.ColName;
                tmpStr += ", ";
            }
            return tmpStr.Substring(0, tmpStr.Length - 2);
        }

        public string GetParamModelLst()
        {
            string strPara = string.Empty;
            foreach (var col in TblCols)
            {
                strPara += col.GetParamModel();
            }
            return strPara;
        }

        public string GetParamDeclLst()
        {
            string strPara = string.Empty;
            foreach (var col in TblCols)
            {
                strPara += col.GetParamDecl();
                strPara += ",\r\n";
            }
            strPara = strPara.Remove(strPara.LastIndexOf(','));
            return strPara;
        }

        public string GetParamContentLst()
        {
            string strPara = string.Empty;
            foreach (var col in TblCols)
            {
                strPara += col.GetParamContent() + "\r\n";
            }
            return strPara;
        }

        public string GetAppendParaListWithoutIndex()
        {
            string strPara = string.Empty;
            foreach (var col in TblCols)
            {
                if (!col.Primary)
                {
                    strPara += col.GetAppendPara() + "\r\n";
                }
            }
            return strPara;
        }

        public string GetKeyIndexDecl()
        {
            string strPara = string.Empty;
            switch (TblCols[0].DataType)
            {
                case SqlDbType.Int:
                    strPara += "int ";
                    break;

                case SqlDbType.VarChar:
                case SqlDbType.NVarChar:
                    strPara += "string ";
                    break;

                default:
                    break;
            }
            strPara += TblCols[0].ColName.ToLower();
            return strPara;
        }

        public string GetKeyParamDecl()
        {
            string strPara = "new SqlParameter(\"@";
            strPara += TblCols[0].ColName.ToLower();
            strPara += "\", SqlDbType.";
            strPara += TblCols[0].DataType.ToString();
            if (TblCols[0].Length != 0)
            {
                strPara += " ," + TblCols[0].Length.ToString();
            }
            strPara += ")";
            return strPara;
        }
    }
}